﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FinanSoft.Entities;
using FinanSoft.DataLayer;
using FinanSoft.Utilities;

namespace FinanSoft.BusinessLayer.BuySaleStrategy
{
    public class MerchandiseDocManager : BuySaleDocManager
    {

        #region Atributos
        private bool _IsError;
        private String _ErrorMessage;
        #endregion

        #region Constructor
        public MerchandiseDocManager()
        {
            _IsError = false;
            _ErrorMessage = "";
        }
        #endregion 

        #region Propiedades
        /// <summary>
        /// Devuelve si hubo o no un error
        /// </summary>
        public bool IsError
        {
            get { return _IsError; }
            set { _IsError = value; }
        }

        /// <summary>
        /// Devuelve el mensaje de error
        /// </summary>
        public String ErrorMessage
        {
            get { return _ErrorMessage; }
            set { _ErrorMessage = value; }
        }

        #endregion

        #region Métodos
        /// <summary>
        /// Método que se encarga de guardar un documento de tipo entrada o entrega de mercancías
        /// </summary>
        /// <param name="document">Documento que se va a guardar</param>
        /// <param name="docType">Tipo de documento EM o EE...</param>
        /// <returns>Retorna si hubo o no éxito en la operación</returns>
        public bool SaveDocument(Entities.Document document, string docType)
        {
            // Se obtiene el tipo de documento
            DocType type = DocumentTypeManager.GetInstance().GetType(docType);
            // Verificamos que haya suficientes artículos para cada detalle en caso de que sea salida de mercancías
            if(docType.Equals(Constants.EE_ACCOUNTING_ENTRY))
                foreach (DocDetail detail in document.detalleDoc)
                    if (detail.Item.GetStoreRoomInfo(detail.StoreRoom.Id).Stock < detail.Quantity)
                    {
                        _IsError = true;
                        _ErrorMessage = Constants.NO_ENOUGH_UNITS;
                        return false;
                    }
            // Se intenta guardar en bd el encabezado del documento primero para que nos devuelva el id
            int docId = BuySaleDataManager.GetInstance().SaveDocumentHeader(document, type);
            if (docId == Constants.INVALID_ID)
            {
                _IsError = true;
                _ErrorMessage = Constants.ERROR_SAVING_DOC;
                return false;
            }
            // Intentamos guardar los artículos para el documento que se insertó anteriormente
            foreach (DocDetail detail in document.detalleDoc)
            {
                double localUnitCost = Math.Round(detail.UnitCost * MoneyManager.GetInstance().GetCurrency(document.IdMoneda).ToLocalCurrency, 2);
                // Establecemos la información de asientos
                int otherId;
                if(docType.Equals(Constants.EM_ACCOUNTING_ENTRY))
                {
                    otherId = CatalogManager.GetInstance().GetAccountingCatalog().GetSpecialAccounts(Constants.SpecialType.allocationInventory)[0].AccountID;
                    bool result = ItemManager.GetInstance().MakeInventoryInputMovement(detail.Item.Id, detail.StoreRoom.Id, localUnitCost, (int) Math.Round(detail.Quantity), otherId, Constants.INVALID_ID, docType);
                    if(!result)
                    {
                        _ErrorMessage = ItemManager.GetInstance().ErrorMessage;
                        return false;
                    }
                }
                else
                {
                    otherId = detail.Item.GetStoreRoomInfo(detail.StoreRoom.Id).CuentaCostoVentas.AccountID;
                    bool result = ItemManager.GetInstance().MakeInventoryOutputMovement(detail.Item.Id, detail.StoreRoom.Id, (int)Math.Round(detail.Quantity), otherId, Constants.INVALID_ID, docType);
                    if (!result)
                    {
                        _ErrorMessage = ItemManager.GetInstance().ErrorMessage;
                        return false;
                    }
                }
                bool noErrorDB = BuySaleDataManager.GetInstance().SaveDocumentArticle(detail, docId);
                if (!noErrorDB)
                {
                    _IsError = true;
                    _ErrorMessage = Constants.ERROR_SAVING_DOCS_ARTICLES;
                    return false;
                }
                else
                {
                    ItemStoreRoomInfo itemStoreInfo = detail.Item.GetStoreRoomInfo(detail.StoreRoom.Id);
                    if (docType == Constants.EE_ACCOUNTING_ENTRY && document.BaseDocId != Constants.INVALID_ID)
                        itemStoreInfo.Comprometido -= (int)Math.Round(detail.Quantity);
                    if (docType == Constants.EM_ACCOUNTING_ENTRY && document.BaseDocId != Constants.INVALID_ID)
                        itemStoreInfo.Solicitado -= (int)Math.Round(detail.Quantity);
                }
            }
            DocumentTypeManager.GetInstance().IncreaseDocumentConsecutiveNumber(docType);
            return true;
        }

        public string GetErrorMessage()
        {
            return _ErrorMessage;
        }
        #endregion
    }
}
